package com.fmsh.nfcsensor.utils;

import com.fmsh.nfcsensor.bean.GasIndexAlgorithmParams;

/**
 * @author wuyajiang
 * @date 2022/11/18
 */
public class GasUtils {

    public static final int GasIndexAlgorithm_ALGORITHM_TYPE_VOC = 0;
    public static final int GasIndexAlgorithm_ALGORITHM_TYPE_NOX = 1;
    public static final float GasIndexAlgorithm_DEFAULT_SAMPLING_INTERVAL = 1.f;
    public static final float GasIndexAlgorithm_INITIAL_BLACKOUT = 45.f;
    public static final float GasIndexAlgorithm_INDEX_GAIN = 230.f;
    public static final float GasIndexAlgorithm_SRAW_STD_INITIAL = 50.f;
    public static final float GasIndexAlgorithm_SRAW_STD_BONUS_VOC = 220.f;
    public static final float GasIndexAlgorithm_SRAW_STD_NOX = 2000.f;
    public static final float GasIndexAlgorithm_TAU_MEAN_HOURS = 12.f;
    public static final float GasIndexAlgorithm_TAU_VARIANCE_HOURS = 12.f;
    public static final float GasIndexAlgorithm_TAU_INITIAL_MEAN_VOC = 20.f;
    public static final float GasIndexAlgorithm_TAU_INITIAL_MEAN_NOX = 1200.f;
    public static final float GasIndexAlgorithm_INIT_DURATION_MEAN_VOC = 3600.f * 0.75f;

    public static final float GasIndexAlgorithm_INIT_DURATION_MEAN_NOX = 3600.f * 4.75f;

    public static final float GasIndexAlgorithm_INIT_TRANSITION_MEAN = 0.01f;
    public static final float GasIndexAlgorithm_TAU_INITIAL_VARIANCE = 2500.f;
    public static final float GasIndexAlgorithm_INIT_DURATION_VARIANCE_VOC = 3600.f * 1.45f;

    public static final float GasIndexAlgorithm_INIT_DURATION_VARIANCE_NOX = 3600.f * 5.70f;

    public static final float GasIndexAlgorithm_INIT_TRANSITION_VARIANCE = 0.01f;
    public static final float GasIndexAlgorithm_GATING_THRESHOLD_VOC = 340.f;
    public static final float GasIndexAlgorithm_GATING_THRESHOLD_NOX = 30.f;
    public static final float GasIndexAlgorithm_GATING_THRESHOLD_INITIAL = 510.f;
    public static final float GasIndexAlgorithm_GATING_THRESHOLD_TRANSITION = 0.09f;
    public static final float GasIndexAlgorithm_GATING_VOC_MAX_DURATION_MINUTES = 60.f * 3.f;

    public static final float GasIndexAlgorithm_GATING_NOX_MAX_DURATION_MINUTES = 60.f * 12.f;

    public static final float GasIndexAlgorithm_GATING_MAX_RATIO = 0.3f;
    public static final float GasIndexAlgorithm_SIGMOID_L = 500.f;
    public static final float GasIndexAlgorithm_SIGMOID_K_VOC = -0.0065f;
    public static final float GasIndexAlgorithm_SIGMOID_X0_VOC = 213.f;
    public static final float GasIndexAlgorithm_SIGMOID_K_NOX = -0.0101f;
    public static final float GasIndexAlgorithm_SIGMOID_X0_NOX = 614.f;
    public static final float GasIndexAlgorithm_VOC_INDEX_OFFSET_DEFAULT = 100.f;
    public static final float GasIndexAlgorithm_NOX_INDEX_OFFSET_DEFAULT = 1.f;
    public static final float GasIndexAlgorithm_LP_TAU_FAST = 20.0f;
    public static final float GasIndexAlgorithm_LP_TAU_SLOW = 500.0f;
    public static final float GasIndexAlgorithm_LP_ALPHA = -0.2f;
    public static final int GasIndexAlgorithm_VOC_SRAW_MINIMUM = 20000;
    public static final int GasIndexAlgorithm_NOX_SRAW_MINIMUM = 10000;
    public static final float GasIndexAlgorithm_PERSISTENCE_UPTIME_GAMMA = 3.f * 3600.f;
    public static final float GasIndexAlgorithm_TUNING_INDEX_OFFSET_MIN = 1;
    public static final float GasIndexAlgorithm_TUNING_INDEX_OFFSET_MAX = 250;
    public static final float GasIndexAlgorithm_TUNING_LEARNING_TIME_OFFSET_HOURS_MIN = 1;
    public static final float GasIndexAlgorithm_TUNING_LEARNING_TIME_OFFSET_HOURS_MAX = 1000;
    public static final float GasIndexAlgorithm_TUNING_LEARNING_TIME_GAIN_HOURS_MIN = 1;
    public static final float GasIndexAlgorithm_TUNING_LEARNING_TIME_GAIN_HOURS_MAX = 1000;
    public static final float GasIndexAlgorithm_TUNING_GATING_MAX_DURATION_MINUTES_MIN = 0;
    public static final float GasIndexAlgorithm_TUNING_GATING_MAX_DURATION_MINUTES_MAX = 3000;
    public static final float GasIndexAlgorithm_TUNING_STD_INITIAL_MIN = 10;
    public static final float GasIndexAlgorithm_TUNING_STD_INITIAL_MAX = 5000;
    public static final float GasIndexAlgorithm_TUNING_GAIN_FACTOR_MIN = 1;
    public static final float GasIndexAlgorithm_TUNING_GAIN_FACTOR_MAX = 1000;
    public static final float GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING = 64.f;
    public static final float GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING = 8.f;
    public static final float GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__FIX16_MAX = 32767.f;


    public static  void GasIndexAlgorithm_init_with_sampling_interval(
            GasIndexAlgorithmParams params, int algorithm_type,
            float sampling_interval) {
        params.mAlgorithm_Type = algorithm_type;
        params.mSamplingInterval = sampling_interval;
        if ((algorithm_type == GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) {
            params.mIndex_Offset = GasIndexAlgorithm_NOX_INDEX_OFFSET_DEFAULT;
            params.mSraw_Minimum = GasIndexAlgorithm_NOX_SRAW_MINIMUM;
            params.mGating_Max_Duration_Minutes =
                    GasIndexAlgorithm_GATING_NOX_MAX_DURATION_MINUTES;
            params.mInit_Duration_Mean = GasIndexAlgorithm_INIT_DURATION_MEAN_NOX;
            params.mInit_Duration_Variance =
                    GasIndexAlgorithm_INIT_DURATION_VARIANCE_NOX;
            params.mGating_Threshold = GasIndexAlgorithm_GATING_THRESHOLD_NOX;
        } else {
            params.mIndex_Offset = GasIndexAlgorithm_VOC_INDEX_OFFSET_DEFAULT;
            params.mSraw_Minimum = GasIndexAlgorithm_VOC_SRAW_MINIMUM;
            params.mGating_Max_Duration_Minutes =
                    GasIndexAlgorithm_GATING_VOC_MAX_DURATION_MINUTES;
            params.mInit_Duration_Mean = GasIndexAlgorithm_INIT_DURATION_MEAN_VOC;
            params.mInit_Duration_Variance =
                    GasIndexAlgorithm_INIT_DURATION_VARIANCE_VOC;
            params.mGating_Threshold = GasIndexAlgorithm_GATING_THRESHOLD_VOC;
        }
        params.mIndex_Gain = GasIndexAlgorithm_INDEX_GAIN;
        params.mTau_Mean_Hours = GasIndexAlgorithm_TAU_MEAN_HOURS;
        params.mTau_Variance_Hours = GasIndexAlgorithm_TAU_VARIANCE_HOURS;
        params.mSraw_Std_Initial = GasIndexAlgorithm_SRAW_STD_INITIAL;
        GasIndexAlgorithm_reset(params);
    }

   public static void GasIndexAlgorithm_init(GasIndexAlgorithmParams params,
                                int algorithm_type) {
        GasIndexAlgorithm_init_with_sampling_interval(
                params, algorithm_type, GasIndexAlgorithm_DEFAULT_SAMPLING_INTERVAL);
    }

    public static void GasIndexAlgorithm_reset(GasIndexAlgorithmParams params) {
        params.mUptime = 0.f;
        params.mSraw = 0.f;
        params.mGas_Index = 0;
        GasIndexAlgorithm__init_instances(params);
    }

    static void GasIndexAlgorithm__init_instances(GasIndexAlgorithmParams params) {

        GasIndexAlgorithm__mean_variance_estimator__set_parameters(params);
        GasIndexAlgorithm__mox_model__set_parameters(
                params, GasIndexAlgorithm__mean_variance_estimator__get_std(params),
                GasIndexAlgorithm__mean_variance_estimator__get_mean(params));
        if ((params.mAlgorithm_Type == GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) {
            GasIndexAlgorithm__sigmoid_scaled__set_parameters(
                    params, GasIndexAlgorithm_SIGMOID_X0_NOX,
                    GasIndexAlgorithm_SIGMOID_K_NOX,
                    GasIndexAlgorithm_NOX_INDEX_OFFSET_DEFAULT);
        } else {
            GasIndexAlgorithm__sigmoid_scaled__set_parameters(
                    params, GasIndexAlgorithm_SIGMOID_X0_VOC,
                    GasIndexAlgorithm_SIGMOID_K_VOC,
                    GasIndexAlgorithm_VOC_INDEX_OFFSET_DEFAULT);
        }
        GasIndexAlgorithm__adaptive_lowpass__set_parameters(params);
    }

    void GasIndexAlgorithm_get_sampling_interval(
     GasIndexAlgorithmParams params, float sampling_interval) {
    sampling_interval = params.mSamplingInterval;
    }

    void GasIndexAlgorithm_get_states( GasIndexAlgorithmParams params,
                                      float state0, float state1) {

    state0 = GasIndexAlgorithm__mean_variance_estimator__get_mean(params);
    state1 = GasIndexAlgorithm__mean_variance_estimator__get_std(params);
        return;
    }

    void GasIndexAlgorithm_set_states(GasIndexAlgorithmParams params, float state0,
                                      float state1) {

        GasIndexAlgorithm__mean_variance_estimator__set_states(
                params, state0, state1, GasIndexAlgorithm_PERSISTENCE_UPTIME_GAMMA);
        GasIndexAlgorithm__mox_model__set_parameters(
                params, GasIndexAlgorithm__mean_variance_estimator__get_std(params),
                GasIndexAlgorithm__mean_variance_estimator__get_mean(params));
        params.mSraw = state0;
    }

    void GasIndexAlgorithm_set_tuning_parameters(
            GasIndexAlgorithmParams params, int index_offset,
            int learning_time_offset_hours, int learning_time_gain_hours,
            int gating_max_duration_minutes, int std_initial,
            int gain_factor) {

        params.mIndex_Offset = ((float)(index_offset));
        params.mTau_Mean_Hours = ((float)(learning_time_offset_hours));
        params.mTau_Variance_Hours = ((float)(learning_time_gain_hours));
        params.mGating_Max_Duration_Minutes =
                ((float)(gating_max_duration_minutes));
        params.mSraw_Std_Initial = ((float)(std_initial));
        params.mIndex_Gain = ((float)(gain_factor));
        GasIndexAlgorithm__init_instances(params);
    }



   public static   int GasIndexAlgorithm_process(GasIndexAlgorithmParams params, int sraw
                                   ) {

        if ((params.mUptime <= GasIndexAlgorithm_INITIAL_BLACKOUT)) {
            params.mUptime = (params.mUptime + params.mSamplingInterval);
        } else {
            if (((sraw > 0) && (sraw < 65000))) {
                if ((sraw < (params.mSraw_Minimum + 1))) {
                    sraw = (params.mSraw_Minimum + 1);
                } else if ((sraw > (params.mSraw_Minimum + 32767))) {
                    sraw = (params.mSraw_Minimum + 32767);
                }
                params.mSraw = ((float)((sraw - params.mSraw_Minimum)));
            }
            if (((params.mAlgorithm_Type ==
                    GasIndexAlgorithm_ALGORITHM_TYPE_VOC) ||
                    GasIndexAlgorithm__mean_variance_estimator__is_initialized(
                            params))) {
                params.mGas_Index =
                        GasIndexAlgorithm__mox_model__process(params, params.mSraw);
                params.mGas_Index = GasIndexAlgorithm__sigmoid_scaled__process(
                        params, params.mGas_Index);
            } else {
                params.mGas_Index = params.mIndex_Offset;
            }
            params.mGas_Index = GasIndexAlgorithm__adaptive_lowpass__process(
                    params, params.mGas_Index);
            if ((params.mGas_Index < 0.5f)) {
                params.mGas_Index = 0.5f;
            }
            if ((params.mSraw > 0.f)) {
                GasIndexAlgorithm__mean_variance_estimator__process(params,
                        params.mSraw);
                GasIndexAlgorithm__mox_model__set_parameters(
                        params,
                        GasIndexAlgorithm__mean_variance_estimator__get_std(params),
                        GasIndexAlgorithm__mean_variance_estimator__get_mean(params));
            }
        }
        return  ((int)((params.mGas_Index + 0.5f)));

    }

    static void GasIndexAlgorithm__mean_variance_estimator__set_parameters(
            GasIndexAlgorithmParams params) {

        params.m_Mean_Variance_Estimator___Initialized = false;
        params.m_Mean_Variance_Estimator___Mean = 0.f;
        params.m_Mean_Variance_Estimator___Sraw_Offset = 0.f;
        params.m_Mean_Variance_Estimator___Std = params.mSraw_Std_Initial;
        params.m_Mean_Variance_Estimator___Gamma_Mean =
                (((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING *
                        GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) *
                        (params.mSamplingInterval / 3600.f)) /
                        (params.mTau_Mean_Hours + (params.mSamplingInterval / 3600.f)));
        params.m_Mean_Variance_Estimator___Gamma_Variance =
                ((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING *
                        (params.mSamplingInterval / 3600.f)) /
                        (params.mTau_Variance_Hours + (params.mSamplingInterval / 3600.f)));
        if ((params.mAlgorithm_Type == GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) {
            params.m_Mean_Variance_Estimator___Gamma_Initial_Mean =
                    (((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING *
                            GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) *
                            params.mSamplingInterval) /
                            (GasIndexAlgorithm_TAU_INITIAL_MEAN_NOX +
                                    params.mSamplingInterval));
        } else {
            params.m_Mean_Variance_Estimator___Gamma_Initial_Mean =
                    (((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING *
                            GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) *
                            params.mSamplingInterval) /
                            (GasIndexAlgorithm_TAU_INITIAL_MEAN_VOC +
                                    params.mSamplingInterval));
        }
        params.m_Mean_Variance_Estimator___Gamma_Initial_Variance =
                ((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING *
                        params.mSamplingInterval) /
                        (GasIndexAlgorithm_TAU_INITIAL_VARIANCE + params.mSamplingInterval));
        params.m_Mean_Variance_Estimator__Gamma_Mean = 0.f;
        params.m_Mean_Variance_Estimator__Gamma_Variance = 0.f;
        params.m_Mean_Variance_Estimator___Uptime_Gamma = 0.f;
        params.m_Mean_Variance_Estimator___Uptime_Gating = 0.f;
        params.m_Mean_Variance_Estimator___Gating_Duration_Minutes = 0.f;
    }

    static void GasIndexAlgorithm__mean_variance_estimator__set_states(
            GasIndexAlgorithmParams params, float mean, float std,
            float uptime_gamma) {

        params.m_Mean_Variance_Estimator___Mean = mean;
        params.m_Mean_Variance_Estimator___Std = std;
        params.m_Mean_Variance_Estimator___Uptime_Gamma = uptime_gamma;
        params.m_Mean_Variance_Estimator___Initialized = true;
    }

    static float GasIndexAlgorithm__mean_variance_estimator__get_std(
     GasIndexAlgorithmParams params) {

        return params.m_Mean_Variance_Estimator___Std;
    }

    static float GasIndexAlgorithm__mean_variance_estimator__get_mean(
     GasIndexAlgorithmParams params) {

        return (params.m_Mean_Variance_Estimator___Mean +
                params.m_Mean_Variance_Estimator___Sraw_Offset);
    }

    static Boolean GasIndexAlgorithm__mean_variance_estimator__is_initialized(
            GasIndexAlgorithmParams params) {

        return params.m_Mean_Variance_Estimator___Initialized;
    }

    static void GasIndexAlgorithm__mean_variance_estimator___calculate_gamma(
            GasIndexAlgorithmParams params) {

        float uptime_limit;
        float sigmoid_gamma_mean;
        float gamma_mean;
        float gating_threshold_mean;
        float sigmoid_gating_mean;
        float sigmoid_gamma_variance;
        float gamma_variance;
        float gating_threshold_variance;
        float sigmoid_gating_variance;

        uptime_limit = (GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__FIX16_MAX -
                params.mSamplingInterval);
        if ((params.m_Mean_Variance_Estimator___Uptime_Gamma < uptime_limit)) {
            params.m_Mean_Variance_Estimator___Uptime_Gamma =
                    (params.m_Mean_Variance_Estimator___Uptime_Gamma +
                            params.mSamplingInterval);
        }
        if ((params.m_Mean_Variance_Estimator___Uptime_Gating < uptime_limit)) {
            params.m_Mean_Variance_Estimator___Uptime_Gating =
                    (params.m_Mean_Variance_Estimator___Uptime_Gating +
                            params.mSamplingInterval);
        }
        GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(
                params, params.mInit_Duration_Mean,
                GasIndexAlgorithm_INIT_TRANSITION_MEAN);
        sigmoid_gamma_mean =
                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                        params, params.m_Mean_Variance_Estimator___Uptime_Gamma);
        gamma_mean = (params.m_Mean_Variance_Estimator___Gamma_Mean +
                ((params.m_Mean_Variance_Estimator___Gamma_Initial_Mean -
                        params.m_Mean_Variance_Estimator___Gamma_Mean) *
                        sigmoid_gamma_mean));
        gating_threshold_mean =
                (params.mGating_Threshold +
                        ((GasIndexAlgorithm_GATING_THRESHOLD_INITIAL -
                                params.mGating_Threshold) *
                                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                                        params, params.m_Mean_Variance_Estimator___Uptime_Gating)));
        GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(
                params, gating_threshold_mean,
                GasIndexAlgorithm_GATING_THRESHOLD_TRANSITION);
        sigmoid_gating_mean =
                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                        params, params.mGas_Index);
        params.m_Mean_Variance_Estimator__Gamma_Mean =
                (sigmoid_gating_mean * gamma_mean);
        GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(
                params, params.mInit_Duration_Variance,
                GasIndexAlgorithm_INIT_TRANSITION_VARIANCE);
        sigmoid_gamma_variance =
                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                        params, params.m_Mean_Variance_Estimator___Uptime_Gamma);
        gamma_variance =
                (params.m_Mean_Variance_Estimator___Gamma_Variance +
                        ((params.m_Mean_Variance_Estimator___Gamma_Initial_Variance -
                                params.m_Mean_Variance_Estimator___Gamma_Variance) *
                                (sigmoid_gamma_variance - sigmoid_gamma_mean)));
        gating_threshold_variance =
                (params.mGating_Threshold +
                        ((GasIndexAlgorithm_GATING_THRESHOLD_INITIAL -
                                params.mGating_Threshold) *
                                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                                        params, params.m_Mean_Variance_Estimator___Uptime_Gating)));
        GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(
                params, gating_threshold_variance,
                GasIndexAlgorithm_GATING_THRESHOLD_TRANSITION);
        sigmoid_gating_variance =
                GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
                        params, params.mGas_Index);
        params.m_Mean_Variance_Estimator__Gamma_Variance =
                (sigmoid_gating_variance * gamma_variance);
        params.m_Mean_Variance_Estimator___Gating_Duration_Minutes =
                (params.m_Mean_Variance_Estimator___Gating_Duration_Minutes +
                        ((params.mSamplingInterval / 60.f) *
                                (((1.f - sigmoid_gating_mean) *
                                        (1.f + GasIndexAlgorithm_GATING_MAX_RATIO)) -
                                        GasIndexAlgorithm_GATING_MAX_RATIO)));
        if ((params.m_Mean_Variance_Estimator___Gating_Duration_Minutes < 0.f)) {
            params.m_Mean_Variance_Estimator___Gating_Duration_Minutes = 0.f;
        }
        if ((params.m_Mean_Variance_Estimator___Gating_Duration_Minutes >
                params.mGating_Max_Duration_Minutes)) {
            params.m_Mean_Variance_Estimator___Uptime_Gating = 0.f;
        }
    }

    static void GasIndexAlgorithm__mean_variance_estimator__process(
            GasIndexAlgorithmParams params, float sraw) {

        float delta_sgp;
        float c;
        float additional_scaling;

        if ((params.m_Mean_Variance_Estimator___Initialized == false)) {
            params.m_Mean_Variance_Estimator___Initialized = true;
            params.m_Mean_Variance_Estimator___Sraw_Offset = sraw;
            params.m_Mean_Variance_Estimator___Mean = 0.f;
        } else {
            if (((params.m_Mean_Variance_Estimator___Mean >= 100.f) ||
                    (params.m_Mean_Variance_Estimator___Mean <= -100.f))) {
                params.m_Mean_Variance_Estimator___Sraw_Offset =
                        (params.m_Mean_Variance_Estimator___Sraw_Offset +
                                params.m_Mean_Variance_Estimator___Mean);
                params.m_Mean_Variance_Estimator___Mean = 0.f;
            }
            sraw = (sraw - params.m_Mean_Variance_Estimator___Sraw_Offset);
            GasIndexAlgorithm__mean_variance_estimator___calculate_gamma(params);
            delta_sgp = ((sraw - params.m_Mean_Variance_Estimator___Mean) /
                    GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING);
            if ((delta_sgp < 0.f)) {
                c = (params.m_Mean_Variance_Estimator___Std - delta_sgp);
            } else {
                c = (params.m_Mean_Variance_Estimator___Std + delta_sgp);
            }
            additional_scaling = 1.f;
            if ((c > 1440.f)) {
                additional_scaling = ((c / 1440.f) * (c / 1440.f));
            }
            params.m_Mean_Variance_Estimator___Std =
                    (float) (Math.sqrt((additional_scaling *
                                                (GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING -
                                                        params.m_Mean_Variance_Estimator__Gamma_Variance))) *
                                                Math.sqrt(
                                                        ((params.m_Mean_Variance_Estimator___Std *
                                                                (params.m_Mean_Variance_Estimator___Std /
                                                                        (GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING *
                                                                                additional_scaling))) +
                                                                (((params.m_Mean_Variance_Estimator__Gamma_Variance *
                                                                        delta_sgp) /
                                                                        additional_scaling) *
                                                                        delta_sgp))));
            params.m_Mean_Variance_Estimator___Mean =
                    (params.m_Mean_Variance_Estimator___Mean +
                            ((params.m_Mean_Variance_Estimator__Gamma_Mean * delta_sgp) /
                                    GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING));
        }
    }

    static void
    GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(
            GasIndexAlgorithmParams params, float X0, float K) {

        params.m_Mean_Variance_Estimator___Sigmoid__K = K;
        params.m_Mean_Variance_Estimator___Sigmoid__X0 = X0;
    }

    static float GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(
            GasIndexAlgorithmParams params, float sample) {

        float x;

        x = (params.m_Mean_Variance_Estimator___Sigmoid__K *
                (sample - params.m_Mean_Variance_Estimator___Sigmoid__X0));
        if ((x < -50.f)) {
            return 1.f;
        } else if ((x > 50.f)) {
            return 0.f;
        } else {
            return (float) (1.f / (1.f + Math.exp(x)));
        }
    }

    static void
    GasIndexAlgorithm__mox_model__set_parameters(GasIndexAlgorithmParams params,
                                                 float SRAW_STD, float SRAW_MEAN) {

        params.m_Mox_Model__Sraw_Std = SRAW_STD;
        params.m_Mox_Model__Sraw_Mean = SRAW_MEAN;
    }

    static float
    GasIndexAlgorithm__mox_model__process(GasIndexAlgorithmParams params,
                                          float sraw) {

        if ((params.mAlgorithm_Type == GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) {
            return (((sraw - params.m_Mox_Model__Sraw_Mean) /
                    GasIndexAlgorithm_SRAW_STD_NOX) *
                    params.mIndex_Gain);
        } else {
            return (((sraw - params.m_Mox_Model__Sraw_Mean) /
                    (-1.f * (params.m_Mox_Model__Sraw_Std +
                            GasIndexAlgorithm_SRAW_STD_BONUS_VOC))) *
                    params.mIndex_Gain);
        }
    }

    static void GasIndexAlgorithm__sigmoid_scaled__set_parameters(
            GasIndexAlgorithmParams params, float X0, float K, float offset_default) {

        params.m_Sigmoid_Scaled__K = K;
        params.m_Sigmoid_Scaled__X0 = X0;
        params.m_Sigmoid_Scaled__Offset_Default = offset_default;
    }

    static float
    GasIndexAlgorithm__sigmoid_scaled__process(GasIndexAlgorithmParams params,
                                               float sample) {

        float x;
        float shift;

        x = (params.m_Sigmoid_Scaled__K * (sample - params.m_Sigmoid_Scaled__X0));
        if ((x < -50.f)) {
            return GasIndexAlgorithm_SIGMOID_L;
        } else if ((x > 50.f)) {
            return 0.f;
        } else {
            if ((sample >= 0.f)) {
                if ((params.m_Sigmoid_Scaled__Offset_Default == 1.f)) {
                    shift = ((500.f / 499.f) * (1.f - params.mIndex_Offset));
                } else {
                    shift = ((GasIndexAlgorithm_SIGMOID_L -
                            (5.f * params.mIndex_Offset)) /
                            4.f);
                }
                return (float) (((GasIndexAlgorithm_SIGMOID_L + shift) / (1.f + Math.exp(x))) -
                                        shift);
            } else {
                return (float) ((params.mIndex_Offset /
                                        params.m_Sigmoid_Scaled__Offset_Default) *
                                        (GasIndexAlgorithm_SIGMOID_L / (1.f + Math.exp(x))));
            }
        }
    }

    static void GasIndexAlgorithm__adaptive_lowpass__set_parameters(
            GasIndexAlgorithmParams params) {

        params.m_Adaptive_Lowpass__A1 =
                (params.mSamplingInterval /
                        (GasIndexAlgorithm_LP_TAU_FAST + params.mSamplingInterval));
        params.m_Adaptive_Lowpass__A2 =
                (params.mSamplingInterval /
                        (GasIndexAlgorithm_LP_TAU_SLOW + params.mSamplingInterval));
        params.m_Adaptive_Lowpass___Initialized = false;
    }

    static float
    GasIndexAlgorithm__adaptive_lowpass__process(GasIndexAlgorithmParams params,
                                                 float sample) {

        float abs_delta;
        float F1;
        float tau_a;
        float a3;

        if ((params.m_Adaptive_Lowpass___Initialized == false)) {
            params.m_Adaptive_Lowpass___X1 = sample;
            params.m_Adaptive_Lowpass___X2 = sample;
            params.m_Adaptive_Lowpass___X3 = sample;
            params.m_Adaptive_Lowpass___Initialized = true;
        }
        params.m_Adaptive_Lowpass___X1 =
                (((1.f - params.m_Adaptive_Lowpass__A1) *
                        params.m_Adaptive_Lowpass___X1) +
                        (params.m_Adaptive_Lowpass__A1 * sample));
        params.m_Adaptive_Lowpass___X2 =
                (((1.f - params.m_Adaptive_Lowpass__A2) *
                        params.m_Adaptive_Lowpass___X2) +
                        (params.m_Adaptive_Lowpass__A2 * sample));
        abs_delta =
                (params.m_Adaptive_Lowpass___X1 - params.m_Adaptive_Lowpass___X2);
        if ((abs_delta < 0.f)) {
            abs_delta = (-1.f * abs_delta);
        }
        F1 = (float) Math.exp((GasIndexAlgorithm_LP_ALPHA * abs_delta));
        tau_a = (((GasIndexAlgorithm_LP_TAU_SLOW - GasIndexAlgorithm_LP_TAU_FAST) *
                F1) +
                GasIndexAlgorithm_LP_TAU_FAST);
        a3 = (params.mSamplingInterval / (params.mSamplingInterval + tau_a));
        params.m_Adaptive_Lowpass___X3 =
                (((1.f - a3) * params.m_Adaptive_Lowpass___X3) + (a3 * sample));
        return params.m_Adaptive_Lowpass___X3;
    }

}
